/* Judge Battle: input status and directions, output processes */

var MoveTask = function(troopid, miniTick, atRoute, moveAlready, isLast){
	this.troopid = troopid;
	this.miniTick = miniTick;
	this.atRoute = atRoute;
	this.moveAlready = moveAlready;
	this.isLast = isLast;
};

var MoveTaskQueue = function(){
	this.task = [];
	
	this.Insert = function(moveTask){
		for (var taskid = this.task.length - 1; taskid > -2; taskid--){
			if (taskid < 0 || this.task[taskid].miniTick <= moveTask.miniTick){
				this.task.splice(taskid + 1, 0, moveTask);
				break;
			}
		}
	};
	
	this.RemoveOfTroop = function(startTaskid, troopid){
		if (this.task.length == 0)
			return;
		
		var realCursor = startTaskid;
		for (var taskid = startTaskid; taskid < this.task.length; taskid++){
			if (this.task[taskid].troopid != troopid){
				this.task[realCursor++] = this.task[taskid];
			}
		}
		this.task.splice(realCursor, this.task.length - realCursor);
	};
}

var Judge_ref = function() {
//	for (每一个tick){
//
//		初始化tick-status
//
//		对部队排序,按照strength从大到小
//
//		for (每一个部队){
//			计算移动事务，加入移动事务队列
//		}
//		for (每一个部队){
//			执行一次遭遇规则，如果需要攻击，则攻击；
//		}
//		for (每一个移动事务){
//			移动;
//			如果遭遇，则执行遭遇规则，如果需要攻击，则攻击；输出攻击的部队移除所有事务
//			如果触发附近敌军的跟踪规则，则将跟踪移动事务加入移动事务队列；
//		}
//		for (每一个部队){
//			如果没有战斗/移动，且有常务命令，执行常务;
//			计算常务结果;
//		}
//	}
//	note:移动攻击的同时计算部队的消耗量，补给量
};

var judgeBattle = {
	_time_ref : null,
	_troop : null,
	_zone : null,
	_processData : null,
	
	_troopArray : null,
	_moveTaskQueue : null,
	_originStrength : null,

	Judge : function(){
		this._time_ref = campaign.time_ref;
		this._troop = campaign.troop;
		this._zone = campaign.zone;

		//初始化本次step的作战过程记录
		wholeProcess[this._time_ref.current_step] = [];
		this._processData = wholeProcess[this._time_ref.current_step];
		
		for (var tick = 0; tick < this._time_ref.ticks_of_step; tick++){

			//按照court_force, strength对部队开始顺序进行排序，court_force为第一顺序，strength为第二顺序
			//顺便保存初始strength
			this._troopArray = [];
			this._originStrength = [];
			for (var troopid = 0; troopid < this._troop.length; troopid++){
				this._troopArray[troopid] = troopid;
				this._originStrength[troopid] = this._troop[troopid].strength;
			}
			//冒泡排序，court_force为第一顺序，strength为第二顺序
			for (var maxid = this._troopArray.length - 1; maxid > 0; maxid--){
				for (var tgtid = 0; tgtid < maxid; tgtid++){
					var cmpid = tgtid + 1;
					var tgtTroopid = this._troopArray[tgtid];
					var cmpTroopid = this._troopArray[cmpid];
					var isSwap = false;
					if (this._troop[cmpTroopid].court_force != this._troop[tgtTroopid].court_force){
						isSwap = this._troop[cmpTroopid].court_force;
					}else{
						isSwap = this._troop[cmpTroopid].strength > this._troop[tgtTroopid].strength;
					}
					if (isSwap){
						var tmpTroopid = this._troopArray[tgtid];
						this._troopArray[tgtid] = this._troopArray[cmpid];
						this._troopArray[cmpid] = tmpTroopid;
					}
				}
			}
			
			//初始化移动事务队列
			this._moveTaskQueue = new MoveTaskQueue();

			//计算每个部队的移动路径，加入到移动事务队列
			for (var troopArrayId = 0; troopArrayId < this._troopArray.length; troopArrayId++){
				var troopid = this._troopArray[troopArrayId];
				if (this._troop[troopid].strength <= 0)	continue;
				
				//场外部队，不计算
				if (this._troop[troopid].court_force)
					continue;
				
				//如果已到达最后一个位置，则停驻
				direction[troopid].marchStatus = (direction[troopid].atRoute < direction[troopid].routeTiles.length - 1) ? 1 : 0;
				
				//如果部队已到达最后一个位置，则处于停驻状态，无需移动
				if (direction[troopid].marchStatus <= 0)
					continue;
				
				//如果 处于被牵制/被击溃状态，则本tick无法移动
				if (this._troop[troopid].tieTimer >= campaign.judgement.tie_threshold)
					continue;
				
				//如果trivialMeantime并且tick为单数，则本tick改为执行常务
				if (direction[troopid].trivialMeantime == 1 && tick % 2 == 1)
					continue;
				
				this._BuildMoveTaskQueue(troopid);
			}
			
			//执行一次侦搜任务
			this._TryRecon(tick, -1);
			
			//执行一次遭遇攻击规则
			this._TryAttackEnemy(tick, -1);
			
			//执行移动事务，实时处理遭遇攻击规则
			for (var taskid = 0; taskid < this._moveTaskQueue.task.length; taskid++){
				//没有规则判断是因为需要停驻时，已经将后续移动事务删除
				
				var task = this._moveTaskQueue.task[taskid];
				var troopid = task.troopid;
				var tgtTileIndex = direction[troopid].routeTiles[task.atRoute];
				var noMove = direction[troopid].atRoute == task.atRoute;
				
				if (noMove == false){
					//拥挤规则，如果某个地块的部队超过了3个，则停止移动
					var crowedMap = troopCrowed.GetScriptCrowedMap(this._troop, tileEngine);
					if (crowedMap[tgtTileIndex] >= 3){
						this._moveTaskQueue.RemoveOfTroop(taskid + 1, troopid);
						direction[troopid].marchStatus = 0;
						continue;
					}
				}
				
				direction[troopid].atRoute = task.atRoute;
				direction[troopid].moveAlready = task.moveAlready;
				direction[troopid].moveTimer = 0;
				
				if (task.isLast)
					direction[troopid].marchStatus = 0;
				
				if (noMove)//没有移动
					continue;
				
				//目标部队移动了一格
				this._OnReachNewTile(tick, troopid, tgtTileIndex);
				this._OnGetInfo(tick, troopid, tgtTileIndex, 1);
				
				//执行遭遇攻击规则
				this._TryAttackEnemy(tick, taskid);
			}
			
			//各部队执行常务
			for (var troopArrayId = 0; troopArrayId < this._troopArray.length; troopArrayId++){
				var troopid = this._troopArray[troopArrayId];
				if (this._troop[troopid].strength <= 0)	continue;
				
				//条件：没有行军/攻击 /被牵制/被击溃;
				if (direction[troopid].moveTimer <= 0
					|| direction[troopid].attackTimer <= 0
					|| this._troop[troopid].tieTimer >= campaign.judgement.tie_threshold)
					continue;
				
				if (direction[troopid].trivial < 2){
					this._OnPassIndexTrivial(tick, troopid, direction[troopid].trivial == 0);
				}else if (direction[troopid].trivial < 4){
					this._OnDefendIndexTrivial(tick, troopid, direction[troopid].trivial == 3);
				}else{
					//休整，统一在sumtick的时候进行计算
					direction[troopid].rested = true;
				}
			}

			//tick结算：攻击/移动/牵制 计时器累加，士气增减等
			this._SumTick(tick);
			
		}//tick
		
		//重建每个单位的指令（策略指令不变，路线指令去除已经走完的）
		this._RebuildDirection();
		
	},//Judge
	
	_BuildMoveTaskQueue : function(troopid){
		
		var move = this._troop[troopid].tickMove;

		var atRoute = direction[troopid].atRoute;
		var moveAlready = direction[troopid].moveAlready;

		var isLast = atRoute >= direction[troopid].routeTiles.length - 1;

		while (move > 0 && isLast == false){
			var srcTileIndex = direction[troopid].routeTiles[atRoute];
			var tgtTileIndex = direction[troopid].routeTiles[atRoute + 1];
			var needMove = this._zone.pass_index[srcTileIndex] + this._zone.pass_index[tgtTileIndex] - moveAlready;

			if (move < needMove){
				//无法抵达下一个tile
				moveAlready += move;
				move = 0;
				this._moveTaskQueue.Insert(new MoveTask(troopid, 1.0, atRoute, moveAlready, false));
			}else{
				//完成了一个tile（移动了一步）
				move -= needMove;
				atRoute++;
				moveAlready = 0;
				isLast = atRoute >= direction[troopid].routeTiles.length - 1;

				var miniTick = 1 - (move / this._troop[troopid].tickMove);
				this._moveTaskQueue.Insert(new MoveTask(troopid, miniTick, atRoute, moveAlready, isLast));
			}
		}//while
	},

	_TryAttackEnemy : function(tick, taskid){
		//获取攻击范围内敌军
		for (var troopArrayId = 0; troopArrayId < this._troopArray.length; troopArrayId++){
			var troopid = this._troopArray[troopArrayId];
			if (this._troop[troopid].strength <= 0)	continue;
			
			if (this._troop[troopid].court_force)
				continue;

			var arroundEnemy = campaignHelper.GetArroundEnemy(this._troop[troopid].force,
				this._troop[troopid].tileIndex,
				this._troop[troopid].attack_range,
				this._troop[troopid].attack_efficiency);
			
			if (arroundEnemy.length <= 0)
				continue;
			
			//遭遇停驻规则（非遭遇会在下一tick恢复行军）
			if (direction[troopid].encounter == 1 && direction[troopid].marchStatus == 1){
				//删除后续移动事务
				this._moveTaskQueue.RemoveOfTroop(taskid + 1, troopid);
				direction[troopid].marchStatus = 0;
			}
			
			//攻击：停驻非消极规则，遭遇推进规则
			
			//已经攻击过了，则不攻击
			if (direction[troopid].attackTimer <= 0)
				continue;
			
			//处于击溃状态，则不攻击
			if (this._troop[troopid].tieTimer >= campaign.judgement.retreat_threshold)
				continue;

			//寻找最优先攻击的敌人
			var attackTroopid = -1;
			if (direction[troopid].marchStatus == 0){
				//停驻非消极规则-攻击
				if (direction[troopid].battle == 0){
					var ADRateHighest = 0;
					for (var idx = 0; idx < arroundEnemy.length; idx++){
						var tgtTroopid = arroundEnemy[idx];
						if (this._troop[tgtTroopid].attackDefendRate > ADRateHighest){
							ADRateHighest = this._troop[tgtTroopid].attackDefendRate;
							attackTroopid = tgtTroopid;
						}
					}
				}
			}
			else if (direction[troopid].marchStatus == 1){
				//处在进攻路径中的敌军（遭遇推进规则、遭遇迂回规则）
				var tgtTileIndex = direction[troopid].routeTiles[direction[troopid].atRoute + 1];
				for (var idx = 0; idx < arroundEnemy.length; idx++){
					var tgtTroopid = arroundEnemy[idx];
					if (this._troop[tgtTroopid].tileIndex == tgtTileIndex){
						attackTroopid = tgtTroopid;
						break;
					}
				}
			}
			
			//找到了需要攻击的敌人
			if (attackTroopid < 0)
				continue;
			
			var tileIndex = this._troop[troopid].tileIndex;
			var attackTileIndex = this._troop[attackTroopid].tileIndex;
			
			//删除后续移动事务
			this._moveTaskQueue.RemoveOfTroop(taskid + 1, troopid);
			
			direction[troopid].attackTimer = 0;
			
			//敌人是否会反击（1.敌人该tick未攻击过，2.敌人未处于击溃状态，3.敌人攻击距离足够）
			var isCounterattack = (direction[attackTroopid].attackTimer > 0) && (this._troop[attackTroopid].tieTimer < campaign.judgement.retreat_threshold);
			if (isCounterattack){
				var rangePay = tileEngine.RoutePay(this._zone.direct_index, attackTileIndex, tileIndex, false);
				isCounterattack = rangePay.pay >= 0 && this._troop[attackTroopid].attack_range >= rangePay.pay;
			}
			
			if (isCounterattack){
				this._moveTaskQueue.RemoveOfTroop(taskid + 1, attackTroopid);
				direction[attackTroopid].attackTimer = 0;
			}
			
			this._OnAtttackEnemy(tick, troopid, attackTroopid, tileIndex, attackTileIndex, isCounterattack);
			this._OnGetInfo(tick, attackTroopid, tileIndex, 0);
			
			//如果攻击者死亡，则加入死亡过程
			if (this._troop[troopid].strength <= 0){
				this._OnDie(tick, troopid, tileIndex);
			}
			
			//如果被攻击者死亡，则加入死亡过程
			if (this._troop[attackTroopid].strength <= 0){
				this._OnDie(tick, attackTroopid, attackTileIndex);
			}else{
				//尝试牵制/击退规则
				this._TryTie(tick, taskid, attackTroopid, attackTileIndex);
			}
		}
	},
	
	_TryTie : function(tick, taskid, troopid, tileIndex){
		//如果被攻击的一方伤害超过阈值，则被牵制，或被击溃
		var damagePercent = (this._originStrength[troopid] - this._troop[troopid].strength) / this._originStrength[troopid];
		if (damagePercent >= campaign.judgement.retreat_damage){
			this._OnTroopStatus(tick, troopid, tileIndex, campaign.judgement.retreat_tietimer, -1);
		}else if (damagePercent >= campaign.judgement.hurt_damage && this._troop[troopid].tieTimer < campaign.judgement.hurt_tietimer){
			this._OnTroopStatus(tick, troopid, tileIndex, campaign.judgement.hurt_tietimer, -1);
		}else if (damagePercent >= campaign.judgement.tie_damage && this._troop[troopid].tieTimer < campaign.judgement.tie_tietimer){
			this._OnTroopStatus(tick, troopid, tileIndex, campaign.judgement.tie_tietimer, -1);
		}
		
		//场外部队没有撤退概念
		if (this._troop[troopid].court_force)
			return;

		//如果被攻击者被牵制，则删除其后续移动任务
		if (this._troop[troopid].tieTimer < campaign.judgement.tie_threshold)
			return;

		this._moveTaskQueue.RemoveOfTroop(taskid + 1, troopid);

		//如果被击溃，则后退
		if (this._troop[troopid].tieTimer < campaign.judgement.retreat_threshold)
			return;
		
		//尝试撤退
		this._TryRetreat(tick, troopid, tileIndex);
	},
	
	_TryRetreat : function(tick, troopid, tileIndex){
		var costMap = ForceInfo.GetTroopPassIndex(forceInfo[this._troop[troopid].force], campaign, tileEngine, troopid, true, true);
		var tickMove = this._troop[troopid].tickMove;
		
		var retreatTileIndex = -1;
		if (direction[troopid].atRoute > 0){
			//如果存在RouteTiles，则直接后退
			var tileIndex_tmp = direction[troopid].routeTiles[direction[troopid].atRoute - 1];
			if (costMap[tileIndex_tmp] < 0
				|| costMap[tileIndex] + costMap[tileIndex_tmp] > 3 * tickMove)
				return;
			
			retreatTileIndex = tileIndex_tmp;
			
			direction[troopid].atRoute--;
		}else{
			//如果不存在，则选择最近的，可以后退的位置后退，并将该位置排入移动路径第一个点
			var minPass = 5000;
			var minTileIndex = -1;
			for (var neighborid in tileEngine.neighborCache[tileIndex]){
				var tileIndex_tmp = tileEngine.neighborCache[tileIndex][neighborid];
				
				if (costMap[tileIndex_tmp] >= 0 && costMap[tileIndex_tmp] < minPass){
					minPass = costMap[tileIndex_tmp];
					minTileIndex = tileIndex_tmp;
				}
			}
			
			if (minTileIndex == -1
				|| costMap[tileIndex] + costMap[minTileIndex] > 3 * tickMove)
				return;
			
			retreatTileIndex = minTileIndex;
			
			//将该位置插入移动路径第一个点（之后的点序号全部+1）
			direction[troopid].routeTiles.splice(0,0,retreatTileIndex);
			for (var idx = 0; idx < direction[troopid].attackIdxOfRoute; idx++){
				direction[troopid].attackIdxOfRoute[idx]++;
			}
			direction[troopid].attackIdxOfRoute.splice(0,0,0);
		}
		if (retreatTileIndex >= 0){
			this._OnReachNewTile(tick, troopid, retreatTileIndex);
			this._OnGetInfo(tick, troopid, retreatTileIndex, 1);
		}
	},
	
	_TryRecon : function(tick, taskid){
		//获取攻击范围内敌军
		for (var troopArrayId = 0; troopArrayId < this._troopArray.length; troopArrayId++){
			var troopid = this._troopArray[troopArrayId];
			if (this._troop[troopid].strength <= 0)	continue;

			if (this._troop[troopid].court_force == false)
				continue;
			
			if (direction[troopid].routeTiles.length < 2)
				continue;
			
			//处于牵制/击溃状态，则不攻击
			if (this._troop[troopid].tieTimer >= campaign.judgement.tie_threshold)
				continue;
			
			direction[troopid].moveTimer = 0;
			
			var tileIndex = direction[troopid].routeTiles[1];
			
			//侦搜目标区域的情报
			this._OnGetInfo(tick, troopid, tileIndex, 1);

			var arroundEnemy = campaignHelper.GetArroundEnemy(
				this._troop[troopid].force,
				tileIndex,
				this._troop[troopid].attack_range,
				this._troop[troopid].attack_efficiency);
			
			var attackTroopid = -1;
			var maxEnemyAttack = 0;
			var maxEnemyADRate = 0;
			for (var idx = 0; idx < arroundEnemy.length; idx++){
				var tgtTroopid = arroundEnemy[idx];
				
				//优先寻找对自身威胁最大的部队，其次寻找本身价值最大的部队
				var typeid = this._troop[troopid].troop_type;
				var attack_efficiency = this._troop[tgtTroopid].attack_efficiency[typeid];
				if (attack_efficiency > maxEnemyAttack){
					maxEnemyAttack = this._troop[tgtTroopid].attack_efficiency[typeid];
					attackTroopid = tgtTroopid;
				}else if (attack_efficiency == maxEnemyAttack){
					if (this._troop[tgtTroopid].attackDefendRate > maxEnemyADRate){
						maxEnemyADRate = this._troop[tgtTroopid].attackDefendRate;
						attackTroopid = tgtTroopid;
					}
				}
			}
			if (attackTroopid >= 0){
				direction[troopid].attackTimer = 0;
				if (maxEnemyAttack > 0){
					direction[attackTroopid].attackTimer = 0;
					this._moveTaskQueue.RemoveOfTroop(0, attackTroopid);
				}
			}
			
			this._OnRecon(tick, troopid, attackTroopid, tileIndex, maxEnemyAttack > 0);
			
			if (attackTroopid < 0)
				return;
			
			var attackTileIndex = this._troop[attackTroopid].tileIndex;
						
			//如果攻击者死亡，则加入死亡过程
			if (this._troop[troopid].strength <= 0){
				this._OnDie(tick, troopid, tileIndex);
			}else{
				//直接尝试牵制/溃败规则 (只有主动进攻，没有被动还击)
				this._TryTie(tick, taskid, troopid, tileIndex);
			}

			//如果被攻击者死亡，则加入死亡过程
			if (this._troop[attackTroopid].strength <= 0){
				this._OnDie(tick, attackTroopid, attackTileIndex);
			}else{
				//尝试牵制/溃败规则
				this._TryTie(tick, taskid, attackTroopid, attackTileIndex);
			}
		}
	},

	_RebuildDirection : function(){
		for (var troopid in direction){
			if (this._troop[troopid].strength <= 0) continue;
			
			//空军没有行军过程，没有需要修改的地方
			if (this._troop[troopid].court_force)
				continue;
			
			//只重设下回合要操作的单位
			if (this._troop[troopid].force == this._time_ref.force_of_step)
				continue;
			
			if (direction[troopid].marchStatus == 0){
				direction[troopid].routeTiles = [this._troop[troopid].tileIndex];
				direction[troopid].attackIdxOfRoute = [0];
				direction[troopid].atRoute = 0;
				direction[troopid].moveAlready = 0;
				direction[troopid].arranged = false;
			}else{
				var originRoute = direction[troopid].atRoute;
				var routeTiles = [];
				for (var idx = originRoute; idx < direction[troopid].routeTiles.length; idx++)
					routeTiles[routeTiles.length] = direction[troopid].routeTiles[idx];
				var attackIdxOfRoute = [0];
				for (var idx = 0; idx < direction[troopid].attackIdxOfRoute.length; idx++){
					if (direction[troopid].attackIdxOfRoute[idx] > originRoute)
						attackIdxOfRoute[attackIdxOfRoute.length] = direction[troopid].attackIdxOfRoute[idx] - originRoute;
				}
				direction[troopid].routeTiles = routeTiles;
				direction[troopid].attackIdxOfRoute = attackIdxOfRoute;
				direction[troopid].atRoute = 0;
			}
		}
	},
	
	_SumTick : function(tick){
		for (var troopid = 0; troopid < direction.length; troopid++){
			if (this._troop[troopid].strength <= 0) continue;

			//decrease tieTimer, calc morale
			var morale = this._troop[troopid].morale;
			var morale_ori = morale;
			morale += campaign.judgement.tick_morale;
			
			if (direction[troopid].attackTimer == 0){
				morale += campaign.judgement.battle_morale;
			}
			
			if (direction[troopid].rested){
				morale += campaign.judgement.rest_morale;
				direction[troopid].rested = false;
			}
			
			var tieTimer = this._troop[troopid].tieTimer;
			var tieTimerChanged = tieTimer > 0;
			if (tieTimerChanged > 0){
				tieTimer--;

				if (tieTimer >= campaign.judgement.retreat_threshold){
					morale += campaign.judgement.retreat_morale;
				}else if (tieTimer >= campaign.judgement.hurt_threshold){
					morale += campaign.judgement.hurt_morale;
				}else if (tieTimer >= campaign.judgement.tie_threshold){
					morale += campaign.judgement.tie_morale;
				}
			}
			
			morale = morale > 1 ? 1 : morale;
			morale = morale < 0 ? 0 : morale;
			
			var moraleChanged = morale != morale_ori;
			
			if (moraleChanged || tieTimerChanged)
				this._OnTroopStatus(tick, troopid, this._troop[troopid].tileIndex,
						(tieTimerChanged ? tieTimer : -1),
						(moraleChanged ? morale : -1) );
			
			//如果士气低于临界点，则投降
			if (this._troop[troopid].morale < campaign.judgement.surrend_morale){
				this._OnSurrend(tick, troopid, this._troop[troopid].tileIndex);
			}

			direction[troopid].moveTimer++;
			direction[troopid].attackTimer++;
		}
	},
	
	//process builder ======================================
	
	_OnGetInfo : function(tick, troopid, tileIndex, range){
		var data = new ProcessData(
			tick,
			processGetInfo.id,
			troopid,
			tileIndex,
			processGetInfo.CreateParam(range),
			processGetInfo.duration
		);
		processCursor[data.type].Modify(data);
		this._processData[this._processData.length] = data;
	},
	
	_OnReachNewTile : function(tick, troopid, goingTileIndex){
		var oriCoord = tileEngine.IndexToCoord(this._troop[troopid].tileIndex);
		var tgtCoord = tileEngine.IndexToCoord(goingTileIndex);
		var orientation = orientationEngine.HeadingToOrientation(TwoPointHeading(oriCoord, tgtCoord));
		var data = new ProcessData(
			tick,
			processMove.id,
			troopid,
			goingTileIndex,
			processMove.CreateParam(this._troop[troopid].orientation, orientation),
			processMove.duration
		);
		processCursor[data.type].Modify(data);
		this._processData[this._processData.length] = data;
	},
	
	_OnAtttackEnemy : function(tick, troopidAttack, troopidDefend, tileIndex, attackTileIndex, isCounterattack){
		var damage = new AttackDamage(troopidAttack, troopidDefend, isCounterattack);
		var strength = {
			strengthAttack : this._troop[troopidAttack].strength - damage.damageAttack,
			strengthDefend : this._troop[troopidDefend].strength - damage.damageDefend
		};
		var oriCoord = tileEngine.IndexToCoord(tileIndex);
		var tgtCoord = tileEngine.IndexToCoord(attackTileIndex);
		var orientation = orientationEngine.HeadingToOrientation(TwoPointHeading(oriCoord, tgtCoord));
		var data = new ProcessData(
			tick,
			processAttack.id,
			troopidAttack,
			attackTileIndex,
			processAttack.CreateParam(troopidDefend, damage, strength, this._troop[troopidAttack].orientation, orientation),
			processAttack.duration
		);
		processCursor[data.type].Modify(data);
		this._processData[this._processData.length] = data;
	},
	
	_OnDie : function(tick, troopid, tileIndex){
		var data = new ProcessData(
			tick,
			processMiss.id,
			troopid,
			tileIndex,
			processMiss.CreateParam(),
			processMiss.duration
		);
		processCursor[data.type].Modify(data);
		this._processData[this._processData.length] = data;
	},
	
	_OnSurrend : function(tick, troopid, tileIndex){
		var data = new ProcessData(
			tick,
			processSurrend.id,
			troopid,
			tileIndex,
			processSurrend.CreateParam(),
			processSurrend.duration
		);
		processCursor[data.type].Modify(data);
		this._processData[this._processData.length] = data;
	},
	
	_OnTroopStatus : function(tick, troopid, tileIndex, tieTimer, morale){
		var data = new ProcessData(
			tick,
			processTroopStatus.id,
			troopid,
			tileIndex,
			processTroopStatus.CreateParam(tieTimer, morale),
			processTroopStatus.duration
		);
		processCursor[data.type].Modify(data);
		this._processData[this._processData.length] = data;
	},
	
	_OnRecon : function(tick, troopidAttack, troopidDefend, tileIndex, isCounterattack){
		var damage = null;
		var strength = null;
		if (troopidDefend >= 0){
			damage = new AttackDamage(troopidAttack, troopidDefend, isCounterattack);
			strength = {
				strengthAttack : this._troop[troopidAttack].strength - damage.damageAttack,
				strengthDefend : this._troop[troopidDefend].strength - damage.damageDefend
			};
		}
		var data = new ProcessData(
			tick,
			processRecon.id,
			troopidAttack,
			tileIndex,
			processRecon.CreateParam(troopidDefend, damage, strength),
			processRecon.duration
		);
		processCursor[data.type].Modify(data);
		this._processData[this._processData.length] = data;
	},
	
	_OnPassIndexTrivial : function(tick, troopid, isUp){
		var tgtTileIndex = this._troop[troopid].tileIndex;
		var man = campaign.troop[troopid].strength * campaign.troop[troopid].man_strength;
		var pass_index = campaign.zone.pass_index[tgtTileIndex];
		var passDiv = PassIndexDiv(man, pass_index, isUp);
		var data = new ProcessData(
				tick,
				processPassIndex.id,
				troopid,
				tgtTileIndex,
				processPassIndex.CreateParam(passDiv),
				processPassIndex.duration
		);
		processCursor[data.type].Modify(data);
		this._processData[this._processData.length] = data;
	},

	_OnDefendIndexTrivial : function(tick, troopid, isUp){
		var tgtTileIndex = this._troop[troopid].tileIndex;
		var man = campaign.troop[troopid].strength * campaign.troop[troopid].man_strength;
		var defend_index = campaign.zone.defend_index[tgtTileIndex];
		var defendDiv = DefendIndexDiv(man, defend_index, isUp);
		var defendRate = Math.exp(-0.013863 * (defend_index + defendDiv));
		var data = new ProcessData(
				tick,
				processDefendIndex.id,
				troopid,
				tgtTileIndex,
				processDefendIndex.CreateParam(defendDiv),
				processDefendIndex.duration
		);
		processCursor[data.type].Modify(data);
		this._processData[this._processData.length] = data;
	}
};